package com.we823.project.controller.repo;

import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.google.common.collect.Lists;
import com.we823.project.common.file.in.ReadBomUtil;
import com.we823.project.common.file.in.ReadMaterialUtil;
import com.we823.project.common.file.in.ReadStockUtil;
import com.we823.project.common.web.status.PermissionStatus;
import com.we823.project.controller.base.AbstractPermissionBaseController;
import com.we823.project.core.web.WebConstants;
import com.we823.project.model.repo.MaterialBomModel;
import com.we823.project.model.repo.MaterialModel;
import com.we823.project.model.repo.MaterialStockModel;
import com.we823.project.repository.service.repo.CategoryService;
import com.we823.project.repository.service.repo.MaterialBomService;
import com.we823.project.repository.service.repo.MaterialService;
import com.we823.project.repository.service.repo.MaterialStockService;
import com.we823.utils.web.RequestUtil;

@Controller
@RequestMapping(WebConstants.REPO_INITDATA)
public class InitDataController extends AbstractPermissionBaseController {
	
	private String baseUrl = WebConstants.REPO_INITDATA_TEMPLATE;
	
	private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(InitDataController.class);
	
	private List<MaterialStockModel> materialStockModels = null;
	private List<MaterialBomModel> materialBomModels = null;
	private List<MaterialModel> materialModels = null;
	
	@Autowired
	private MaterialStockService materialStockService;
	@Autowired
	private MaterialBomService materialBomService;
	@Autowired
	private MaterialService materialService;
	@Autowired
	private CategoryService categoryService;
	
	public InitDataController(){
		setResourceIdentity("repo:initdata");
	}
	
	@RequestMapping("index")
	public String index(HttpServletRequest request,Model model) {
		
		return baseUrl+"index";
	}
	
	@RequestMapping("initdata")
	@ResponseBody
	public Model initdata(HttpServletRequest request,Model model) {
		int dataType = RequestUtil.getValueByParam(request, "dataType", 0);
		String filename = RequestUtil.getValueByParam(request, "filename");
		int hasHeader = RequestUtil.getValueByParam(request, "hasHeader", 0);
		String fullFilename = "";
		if(!StringUtils.isEmpty(filename)) {
			fullFilename = request.getServletContext().getRealPath("/")+filename;
		}
		switch (dataType) {
		case 0://库存
			initStockData(fullFilename,hasHeader,model);
			break;
		case 1://物料基本信息
			initMaterialData(fullFilename,hasHeader,model);
			break;
		case 2://BOM基本信息
			initBomData(request,fullFilename,hasHeader,model);
			break;
		default:
			break;
		}
		return model;
	}

	@RequestMapping("import")
	@ResponseBody
	public Model importData(HttpServletRequest request,Model model) {
		int dataType = RequestUtil.getValueByParam(request, "dataType", 0);
		int importType = RequestUtil.getValueByParam(request, "importType", -1);
		int hasHeader = RequestUtil.getValueByParam(request, "hasHeader", 0);
		int rowCount = RequestUtil.getValueByParam(request, "rowCount", 0);
		String filename = RequestUtil.getValueByParam(request, "filename");
		String fullFilename = request.getServletContext().getRealPath("/")+filename;
		switch (dataType) {
		case 0://库存
			importStockData(fullFilename,model,importType,hasHeader);
			break;
		case 1://物料基本信息
			importMaterialData(fullFilename,model,importType,hasHeader);
			break;
		case 2://BOM基本信息
			//由于用request的方式无法处理大数据量的处理，故暂时还是采用读取excel的文件处理
			importBomData(request,fullFilename, model,importType,hasHeader);
			break;
		default:
			break;
		}
		return model;
	}

	/**
	 * 
	 * @param fullFilename
	 * @param model
	 * @param importType 0增量更新 1增量覆盖更新 2全新更新
	 */
	private void importBomData(HttpServletRequest request,String fullFilename, Model model,int importType,int hasHeader) {
		File file = new File(fullFilename);
		if (!file.exists()) {
			model.addAttribute("hasError",true);
			model.addAttribute("message","文件不存在");
		}
		else {
			ReadBomUtil readBomUtil = new ReadBomUtil(materialService,materialBomService);
			try {
				boolean headerFirst = hasHeader==0 ? false : true;
				List<MaterialBomModel> materialBomModels = readBomUtil.getDataFromExcelFile(request,file, headerFirst, model,true);
				if (materialBomModels!=null) {
					LOGGER.debug("importBomData count:{}",materialBomModels.size());
					
					Map<String, MaterialBomModel> map = materialBomService.getMapByBomKey();
					
					List<MaterialBomModel> needNewList = Lists.newArrayList();
					int newCount = 0;
					int updateCount = 0;
					if (0==importType) { //增量更新
						
						for (MaterialBomModel excelBom : materialBomModels) {
							String key = excelBom.getCode()+"_"+excelBom.getMaterialCode();
							if(excelBom.getMaterialDesc()!=null && !StringUtils.isEmpty(excelBom.getMaterialDesc())) {
								key+="_"+excelBom.getMaterialDesc();
							}
							if (!map.containsKey(key)) {
								needNewList.add(excelBom);
								newCount++;
							}
						}
					}else if(1==importType) { //增量覆盖导入

						for (MaterialBomModel excelBom : materialBomModels) {
							String key = excelBom.getCode()+"_"+excelBom.getMaterialCode();
							if(excelBom.getMaterialDesc()!=null && !StringUtils.isEmpty(excelBom.getMaterialDesc())) {
								key+="_"+excelBom.getMaterialDesc();
							}
							if (map!=null && map.containsKey(key)) {
								MaterialBomModel oBomModel = map.get(key);
								if (oBomModel!=null) {
									excelBom.setId(oBomModel.getId()); //添加原有的id
									updateCount++;
								}
							}else {
								newCount++;
							}
							needNewList.add(excelBom);
						}
					}
					
					if (needNewList!=null && needNewList.size()>0) {
						
						materialBomService.save(needNewList);
						String message = String.format("共有%s条数据，新增%s条数据，更新%s条数据", materialBomModels.size(),newCount,updateCount);
						LOGGER.debug(message);
						model.addAttribute("message",message);
						model.addAttribute("hasError",false);
					}
				}
				
			} catch (Exception e) {
				model.addAttribute("hasError",true);
				model.addAttribute("message",e.getMessage());
				LOGGER.error(e.getMessage());
			}
		}
		
	}

	/**
	 * 导入物料信息
	 * @param fullFilename
	 * @param hasHeader
	 * @param model
	 */
	private void importMaterialData(String fullFilename,Model model,Integer importType,int hasHeader) {
		File file = new File(fullFilename);
		if (!file.exists()) {
			model.addAttribute("hasError",true);
			model.addAttribute("message","文件不存在");
		}
		else {
			ReadMaterialUtil readMaterialUtil = new ReadMaterialUtil(categoryService);
			try {
				boolean headerFirst = hasHeader==0 ? false : true;
				materialModels = readMaterialUtil.getDataFromExcelFile(file, headerFirst, model);
				if (materialModels!=null) {
					LOGGER.debug("importMaterialData count:{}",materialModels.size());
					
					Map<String, MaterialModel> map = materialService.map();
					
					List<MaterialModel> needNewList = Lists.newArrayList();
					int newCount = 0;
					int updateCount = 0;
					if (0==importType) { //增量更新
						
						for (MaterialModel excelMaterialModel : materialModels) {
							String key = excelMaterialModel.getCode();
							if (!map.containsKey(key)) {
								needNewList.add(excelMaterialModel);
								newCount++;
							}
						}
					}else if(1==importType) { //增量覆盖导入
						for (MaterialModel excelMaterialModel : materialModels) {
							String key = excelMaterialModel.getCode();
							if (map.containsKey(key)) {
								MaterialModel oMaterialModel = map.get(key);
								if (oMaterialModel!=null) {
									excelMaterialModel.setId(oMaterialModel.getId()); //添加原有的id
									updateCount++;
								}
							}else {
								newCount++;
							}
							needNewList.add(excelMaterialModel);
						}
					}
					
					if (needNewList!=null && needNewList.size()>0) {
						try {
						materialService.save(needNewList);
						String message = String.format("共有%s条数据，新增%s条数据，更新%s条数据", materialModels.size(),newCount,updateCount);
						LOGGER.debug(message);
						model.addAttribute("message",message);
						model.addAttribute("hasError",false);
						}catch(Exception ex) {
							model.addAttribute("message","保存数据出错："+ex.getMessage());
							model.addAttribute("hasError",true);
						}
					}
				}else {
					model.addAttribute("message","无法获取Excel中的数据，请检查");
					model.addAttribute("hasError",true);
				}
				
			} catch (Exception e) {
				model.addAttribute("hasError",true);
				model.addAttribute("message",e.getMessage());
			}
		}
		
	}

	/**
	 * 
	 * @param fullFilename
	 * @param model
	 * @param importType
	 * @param hasHeader
	 */
	private void importStockData(String fullFilename, Model model,int importType,int hasHeader) {
		File file = new File(fullFilename);
		if (!file.exists()) {
			model.addAttribute("hasError",true);
			model.addAttribute("message","文件不存在");
		}else {
			model.addAttribute("hasError",false);
			model.addAttribute("message","导入成功");
		}
		if (materialStockModels!=null) {
			materialStockService.save(materialStockModels);
			materialStockModels = null;
			
			model.addAttribute("hasError",false);
		}
		
	}

	private void initStockData(String fullFilename, Integer hasHeader, Model model) {
		File file = new File(fullFilename);
		if (!file.exists()) {
			model.addAttribute("hasError",true);
			model.addAttribute("message","文件不存在");
		}
		else {
			ReadStockUtil readStockUtil = new ReadStockUtil();  
			try {
				boolean header = (hasHeader==0) ? false : true;
				List<MaterialStockModel> materialStockModels = readStockUtil.getDataFromExcel(file, header);

				Integer count = 0;
				if (materialStockModels!=null) {
					count = materialStockModels.size();
				}
				model.addAttribute("hasError",false);
				model.addAttribute("materialStocks",materialStockModels);
				model.addAttribute("message","共有"+count+"条数据");
				
			} catch (Exception e) {
				model.addAttribute("hasError",true);
				model.addAttribute("message",e.getMessage());
			}
		}
		
	}

	private void initMaterialData(String fullFilename, int hasHeader,Model model) {
		File file = new File(fullFilename);
		if (!file.exists()) {
			model.addAttribute("hasError",true);
			model.addAttribute("message","文件不存在");
		}
		else {
			ReadMaterialUtil readMaterialUtil = new ReadMaterialUtil(categoryService);
			try {
				boolean header = (hasHeader==0) ? false : true;
				materialModels = readMaterialUtil.getDataFromExcelFile(file, header, model);
				int count = 0;
				if (materialModels!=null) {
					count = materialModels.size();
				}
				model.addAttribute("count",count);
				model.addAttribute("hasError",false);
				model.addAttribute("materials",materialModels);
				model.addAttribute("message","共有"+count+"条数据");
				
			} catch (Exception e) {
				model.addAttribute("hasError",true);
				model.addAttribute("message",e.getMessage());
			}
		}
	}

	/**
	 * 初始化BOM的文件信息
	 * @param fullFilename
	 * @param model
	 */
	private void initBomData(HttpServletRequest request,String fullFilename, Integer hasHeader,Model model) {
		File file = new File(fullFilename);
		if (!file.exists()) {
			model.addAttribute("hasError",true);
			model.addAttribute("message","文件不存在");
		}
		else {
			ReadBomUtil readBomUtil = new ReadBomUtil(materialService,materialBomService);
			try {
				boolean header = (hasHeader==0) ? false : true;
				List<MaterialBomModel> materialBomModels = readBomUtil.getDataFromExcelFile(request,file, header, model,false);
				int count = 0;
				if (materialBomModels!=null) {
					count = materialBomModels.size();
				}
				model.addAttribute("count",count);
				model.addAttribute("hasError",false);
				model.addAttribute("materialBoms",materialBomModels);
				model.addAttribute("message","共有"+count+"条数据");
				
			} catch (Exception e) {
				model.addAttribute("hasError",true);
				model.addAttribute("message",e.getMessage());
			}
		}
	}
	
	@RequestMapping("download")
	@ResponseBody
	public Model download(HttpServletRequest request,HttpServletResponse response, Model model) throws IOException {
		check(PermissionStatus.CREATE);
		String filename = RequestUtil.getValueByParam(request, "filename");
		String sheetname = RequestUtil.getValueByParam(request, "sheetname");
		if(filename!=null) {
			int index = filename.lastIndexOf(".");
			if (index>0) {
				String tempFilename = StringUtils.lowerCase(filename);
				String tempSheetname = StringUtils.lowerCase(sheetname);
				String tempext = StringUtils.substring(tempFilename,index);
				if(!tempSheetname.endsWith(tempext)) {
					String ext = StringUtils.substring(filename, index);
					sheetname+=ext;
				}
			}
			String fullname = WebConstants.EXCEL_PATH + filename;
			response.addHeader("Content-Disposition", "attachment;filename="+URLEncoder.encode(sheetname,"utf-8"));
			RequestDispatcher dispatcher = request.getRequestDispatcher(fullname);
			try {
				dispatcher.forward(request, response);
			} catch (ServletException e) {
				e.printStackTrace();
			} catch (IOException e) {
				response.flushBuffer();
			}
		}
		return model;
	}

	public List<MaterialModel> getMaterialModels() {
		return materialModels;
	}

	public void setMaterialModels(List<MaterialModel> materialModels) {
		this.materialModels = materialModels;
	}
	
}
